﻿
/// <reference path="_namespace.js" />
/// <reference path="../math/Vector3.js" />
/// <reference path="Colour.js" />

ajax.lang.addNamespace("ajax.drawing");
$imports("ajax.drawing.Colour");
$imports("ajax.math.Vector3");

//-----------------------------------------------------------------------------
ajax.drawing.Face = function(mesh, v1, v2, v3, colorIndex)
{///<summary>Creates a new instance of a 3d face</summary>
 ///<param name="mesh" type="ajax.geometry.Mesh">The mesh this face belongs to</param>
 ///<param name="v1" type="number" integer="true">Index of vertex 1</param>
 ///<param name="v2" type="number" integer="true">Index of vertex 2</param>
 ///<param name="v3" type="number" integer="true">Index of vertex 3</param>
 ///<param name="colorIndex" type="number" integer="true">The mesh colour index of the colour of this face</param>
    this._mesh        = mesh;
    this._colorIndex  = colorIndex;
    this.v1           = v1;
    this.v2           = v2;
    this.v3           = v3;
    // This WILL store the normal of the face but only if the Compute Face Normal is called
    this.normal       = ajax.lang.safeNew("ajax.math.Vector3");       
}


//-----------------------------------------------------------------------------
// statics
ajax.drawing.Face.cast = function(obj)
{///<returns type="ajax.drawing.Face"/>
    return obj;
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.pointInPoly = function(face, vertHit)
{///<summary>Returns true if the hit vector lies within this triangle face</summary>
 ///<param name="face" type="ajax.drawing.Face">The face to check</param>
 ///<param name="vertHit" type="ajax.math.Vector3">The vector to test</param>

    // Missing intellisense for the instance of this class.
    
    // Grab the actual verts of the face in question
    var vertA = face.getMesh().vertexBuffer[face.v1];
    var vertB = face.getMesh().vertexBuffer[face.v2];
    var vertC = face.getMesh().vertexBuffer[face.v3];                
    
    var Vector3 = ajax.math.Vector3;
    
    // Construct the 3 3D Vectors from the hit point to each vertex of the triangle
    var vecP1 = Vector3.subtract(vertA, vertHit);
    var vecP2 = Vector3.subtract(vertB, vertHit);
    var vecP3 = Vector3.subtract(vertC, vertHit);
    
    // Cross product player triangle with triangle lines    
    var vecCP1 = Vector3.cross(vecP1, face.side1);
    var vecCP2 = Vector3.cross(vecP2, face.side2);
    var vecCP3 = Vector3.cross(vecP3, face.side3);
    
    // Get the distance from the endpoint off the cross product to the plane
    // and see if they all fall on the same sine
    var fDist1 = Vector3.dot(vecCP1, face.normal);
    var fDist2 = Vector3.dot(vecCP2, face.normal);
    var fDist3 = Vector3.dot(vecCP3, face.normal);
    
    var iDist1 = Vector3.sign(fDist1);
    var iDist2 = Vector3.sign(fDist2);
    var iDist3 = Vector3.sign(fDist3);
    
    if ( ((iDist1 == iDist2) && (iDist1 == iDist3)) )
        return true;
    
    return false;                 
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.vectorAngle = function(face, vPos)
{///<summary>Returns the angle of a position to a face (normal)</summary>
 ///<param name="face" type="ajax.drawing.Face"/
 ///<param name="vPos" type="ajax.math.Vector3"/>
 
    // Get a vector from the old player position to a known point on the face
    var vPointOfPoly = face.getMesh().vertexBuffer[face.v2];
    var vPosTriangle = ajax.math.Vector3.subtract(vPointOfPoly, vPos);      

    // Normalise it
    vPosTriangle.normalize();

    return ajax.geometry.Math.angleBetweenNormals(vPosTriangle, face.normal);    
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.vectorDistance = function(face, vPos)
{///<summary>Returns the minimum distance of a position vector from a face</summary>
 ///<param name="face" type="ajax.drawing.Face"/
 ///<param name="vPos" type="ajax.math.Vector3"/>
 
    var vecKnownPoint = face.getMesh().vertexBuffer[face.v2];
    // Create a vector from the position to a known point on the face
    var vecTriangle  = ajax.math.Vector3.subtract(vecKnownPoint, vPos);
    // The MIN DISTANCE is the DOT of this vector with the face normal
    return ajax.math.Vector3.dot(vecTriangle, face.normal);
}


// Public properties for MS AJAX
//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype._mesh        = null;
ajax.drawing.Face.prototype._colorIndex  = ajax.drawing.Colour.prototype;
ajax.drawing.Face.prototype.v1           = ajax.math.Vector3.prototype;
ajax.drawing.Face.prototype.v2           = ajax.math.Vector3.prototype;
ajax.drawing.Face.prototype.v3           = ajax.math.Vector3.prototype;
ajax.drawing.Face.prototype.side1        = ajax.math.Vector3.prototype;
ajax.drawing.Face.prototype.side2        = ajax.math.Vector3.prototype;
ajax.drawing.Face.prototype.side3        = ajax.math.Vector3.prototype;
ajax.drawing.Face.prototype.normal       = ajax.math.Vector3.prototype;
ajax.drawing.Face.prototype._planeD      = 0.0;


// Public Mwthods
//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.vectorAngle = function(vPos)
{
    return ajax.drawing.Face.vectorAngle(this, vPos);
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.vectorDistance = function(vPos)
{
    return ajax.drawing.Face.vectorDistance(this, vPos);
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.getMesh     = function()
{///<returns type="ajax.geometry.Mesh"/>
    return this._mesh;    
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.getColorIndex = function()
{
    return this._colorIndex;
}
//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.getColor      = function()
{///<returns type="ajax.drawing.Colour"/>
    return this._mesh.materialColors[this._colorIndex];
}

ajax.drawing.Face.prototype.getPlaneDistance = function()
{///<returns type="number"/>
    return this._planeD;
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.computeSides = function()
{///<summary>Computes the sides for this Face</summary>
 ///<param name="verts" type="Array" elementType="ajax.math.Vecctor3"/>
    var verts = this._mesh.vertexBuffer;
    this.side1 = ajax.math.Vector3.subtract(verts[this.v2], verts[this.v1]);
    this.side2 = ajax.math.Vector3.subtract(verts[this.v3], verts[this.v2]);
    this.side3 = ajax.math.Vector3.subtract(verts[this.v1], verts[this.v3]);
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.computeFaceNormal = function()
{///<summary>Computes the normals for this Face</summary>
 ///<param name="verts" type="Array" elementType="ajax.math.Vecctor3"/>

    var verts = this._mesh.vertexBuffer;
     					
    // create 2 new Vectors for side A & side B
	var sideA = ajax.math.Vector3.subtract(verts[this.v2], verts[this.v1]);	
	var sideB = ajax.math.Vector3.subtract(verts[this.v3], verts[this.v1]);
	//The Normal is the CrossProduct of the two sides, Normalized
	this.normal = ajax.math.Vector3.cross(sideB, sideA);
	this.normal.normalize();	
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.flipNormals = function()
{
    var v3Temp = this.v1;
    this.v1 = this.v3;
    this.v3 = v3Temp;
    
    this.computeFaceNormal();
    this.computeSides();
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.computePlaneDistance = function()
{
    // PlaneD - create it from a known vertex in this face
    // then DotProduct it with the normal of this face to get
    // the plane distance from world origin
    var verts = this._mesh.vertexBuffer;
    var vert  = verts[this.v2];
    this._planeD = ajax.math.Vector3.dot(vert, this.normal);
}

//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.pointInPoly = function(vertHit)
{///<summary>returns true if the passed position vector lies within the polygon of this face (triangle)
    return ajax.drawing.Face.pointInPoly(this, vertHit);
}


//-----------------------------------------------------------------------------
ajax.drawing.Face.prototype.toString = function()
{
    return "ajax.drawing.Face";
}


